<?php
	
	use Workerman\Worker;
	use Workerman\Mysql;
	use \Workerman\Lib\Timer;
	use \Workerman\Protocols\Http;
	use \Workerman\WebServer;
	
	require_once IA_ROOT . "/../Libs/class/debug.class.php";
	require_once IA_ROOT . "/../Libs/class/token.class.php";
    require_once IA_ROOT . "/../Libs/class/PHPMailer/PHPMailer.php";	
    require_once IA_ROOT . "/../Libs/class/PHPMailer/SMTP.php";
    require_once IA_ROOT . "/../Libs/class/PHPMailer/Exception.php";	
	
	// 创建一个Worker监听5051端口，使用tcp协议通讯
	$net_worker = new Worker( SERVER_HOST_2 .":". DEBUG_PORT );
	//处理定时任务的worker线程
	$tm_selecter_looper = new Worker();
	
	// 启动4个进程对外提供服务
	$net_worker->count = 3;
	
	$tm_selecter_looper->count = 1;
	
	// 每2.5秒执行一次
	$tm_selecter_interval = 2.5;
	// 每5秒执行一次device状态更新，如果没有更新，则认为离线
	$tm_device_chker_interval = 5;
    
    // 机器人自动创建校准批次
    $tm_robot_create_batch_looper = new Worker();
	$tm_robot_create_batch_looper->count = 1;
    $tm_robot_create_batch_looper->name = "robot_create_batch";
    $tm_robot_create_batch_interval = 6;
	/*
	$tm_mysql_block_chk = new Worker();
	$tm_mysql_block_chk->count = 1;
	$tm_mysql_block_chk->onWorkerStart = function($worker) use ($tm_device_chker_interval){
		require_once IA_ROOT . "/../Libs/function/comm.func.php";
		Timer::add($tm_device_chker_interval , function()
		{
			$sql  = "SELECT trx_started, trx_mysql_thread_id, trx_query FROM information_schema.innodb_trx;";
			try{
				$return = sql_queryExec($sql);
				if(!count($return)){
					return;
    			}


    			// if(count($return)){
					$ret = $return[0] ;
    			// }
				
				for($i=0;$i<count($ret);$i++){
					$tmstart = $ret[$i]['trx_started'];
					$threadid = $ret[$i]['trx_mysql_thread_id'];
					$query = $ret[$i]['trx_query'];
					if(strtotime(date('Y-m-d H:i:s'))-strtotime($tmstart)>120){
						$sql = "kill $threadid";
						$rt = sql_queryExec($sql);
						//var_dump(  date('Y-m-d H:i:s') . ": mysql block kill :  $threadid\n,exec result: ", $rt) ;
						$sql = "INSERT INTO hf_mes_log_sys
										(type, msg) VALUE (5300,'Mysql block kill :  $threadid [$query]')";
						sql_query($sql);
					}
				}
				
			}catch(PDOException $e){
				$sql = "INSERT INTO hf_mes_log_sys
								(type, msg) VALUE (2000,'".str_replace("'", "\'", $e->getMessage())."')";
				sql_query($sql);
			}
			$ret = null;
			$pdo = null;

			return;			
		});
	};
	*/
	
	//服务启动
	$net_worker->onWorkerStart = function($worker){
		Trigger\Client::connect(SERVER_HOST, TRIGGER_PORT);
		require_once IA_ROOT . "/../Libs/function/comm.func.php";
		spl_autoload_register(function ($class) {
			$a=IA_ROOT . "/../Libs/action_workerman/".$class.".class.php";
			require_once $a ;
		});
		//sql_queryExec("set global event_scheduler = on;");
	};
	
	//reload服务
	$net_worker->onWorkerReload = function($worker){
		Trigger\Client::connect(SERVER_HOST, TRIGGER_PORT);
		require_once IA_ROOT . "/../Libs/function/comm.func.php";
		spl_autoload_register(function ($class) {
			$a=IA_ROOT . "/../Libs/action_workerman/".$class.".class.php";
			require_once $a ;
		});

		
	};
	
	
	//关闭服务/udp无效
	$net_worker->onWorkerStop = function($worker){

	};
	
	
	//客户端链接/udp无效
	$net_worker->onConnect = function($connection){
		//echo "new connection from ip " . $connection->getRemoteIp() . "\n";
	};
	
	
	//客户端断开链接
	$net_worker->onClose = function($connection){
		//echo "connection closed\n";
	};

	
	
	// 接收数据的event
	$net_worker->onMessage = function($connection, $data) use($net_worker){
		// echo "test1111\n";
		// == Xhprof Debuger ==
		if(IA_XHPROF_DEBUG)
			xhprof_enable(XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY);
	
		$ret = action_switch($data); 

		$connection->send($ret);
		
		// == Xhprof Debuger ==
		if(IA_XHPROF_DEBUG){
			$xhprof_data = xhprof_disable();
			
			$sql = "INSERT INTO hf_mes_xhprof_data (addr, parent, node, ct, wt, cpu, mu, pmu) VALUES ";
			
			foreach($xhprof_data as $k=>$v){
				if($k=="main()"){
					$addr = $k;
					$parent = null;
					$node = $k;
					
				}else{
					$ka = explode('==>', $k);
					$addr = $k;
					$parent = $ka[0];
					$node = $ka[1];
					
				}
				$ct     = $v['ct'];
				$wt    = $v['wt'];
				$cpu  = $v['cpu'];
				$mu   = $v['mu'];
				$pmu = $v['pmu'];
				
				$sql = $sql . " ('$addr', '$parent', '$node', $ct, $wt, $cpu, $mu, $pmu) ,";
				////var_dump();
			}
			$sql = rtrim($sql, ",");
			$sql = $sql . "ON DUPLICATE KEY UPDATE ct=ct+VALUES(ct), wt=wt+VALUES(wt), cpu=cpu+VALUES(cpu), mu=mu+VALUES(mu), pmu=pmu+VALUES(pmu);";
			$sql = $sql.";";
			sql_query($sql);
		}
				
	};
	
	// 解释recv data, 跳转对应的action
	function action_switch($recv_data){
		
		$jObj = null;
		// For TCP END
		Http::header("Access-Control-Allow-Origin: *");
		Http::header("Content-type: application/json");
		Http::header("Access-Control-Allow-Headers:access_token");
		
		// For HTTP
                // //var_dump($recv_data);
		try{
			//if($recv_data["post"]["HTTP_CONTENT_TYPE"]=="");
			$jObj = json_decode( $GLOBALS['HTTP_RAW_POST_DATA'] ,true);
            
		}catch(Exception $e){
			Debug::Assert($e->getMessage());
		}
		//var_dump($recv_data["server"]);
		// For HTTP END
		//判断json格式命令是否正确，否则返回false
        
		if(is_null($jObj)){
			$obj = new stdClass();
			$obj->action = "result_last";
			$obj->errcode = 4001;
			$obj->errmsg = "error JSON format command";
			return json_encode($obj);
		}
		
		//@Debug::Assert($jObj['action']);
		// 检查是否存在action参数
		$action = @$jObj['action'];
		if(empty($action)){
			$obj = new stdClass();
			$obj->action = "";
			$obj->errcode = 4001;
			$obj->errmsg = "error JSON format command ['action' parameter does not exist]";
			return json_encode($obj);
		}
		
		// 判断是否get_token请求，如果是校验账号密码
		if($action == "get_token"){
			$username = @$jObj['param']["username"];
			$password = @$jObj['param']["password"];
			$ret = Token::login($username,$password);
			$obj = new stdClass();
			$obj->action = "result_get_token";
			if($ret["error_code"] != 0){
				$obj->errcode = $ret["error_code"];
				$obj->errmsg = $ret["error_msg"];
				$obj->rtval = "";
			}else{
				$obj->errcode = $ret["error_code"];
				$obj->errmsg = "";
				$obj->rtval = $ret["data"];
			}
			return json_encode($obj);

		}

		if($action != "get_department" && $action != "set_user_account"){
            // 检查是否存在头部或上传参数中，是否存在access_token参数
            $header_access_token = @$recv_data["server"]["HTTP_ACCESS_TOKEN"];
            $param_access_token = @$jObj["access_token"];
            $access_token = "";
            if(!empty($header_access_token)){
                $access_token = $header_access_token;
            }elseif(!empty($param_access_token)){
                $access_token = $param_access_token;
            }

            // 判断access_token值是否正确，并且有效
            $ret_check = Token::checkAccessToken($access_token);
            if($ret_check["error_code"] != 0){
                $obj = new stdClass();
                $obj->action = "result_".$action;
                $obj->errcode = $ret_check["error_code"];
                $obj->errmsg = $ret_check["error_msg"];
                $obj->rtval = "";
                return json_encode($obj);

            }
        }

		$errcode = "";
		$errmsg = "";
		$rtval = "";
		$r = NULL;
		
		try{
			// echo $action;
			switch ($action){

				case "get_sys_status":
					$className = $action;
					$fun_obj = call_user_func(array($className, "create"));
					@$r = $fun_obj->entry($jObj['param']);
					if(empty($r))
						throw new Exception("Process function failed");
					$errcode = $r["errcode"];
					$errmsg = $r["errmsg"];
					$rtval = $r["rtval"];
					break;

                case "get_validate_logon":
					$className = $action;
					$fun_obj = call_user_func(array($className, "create"));
					@$r = $fun_obj->entry($jObj['param']);
					if(empty($r))
						throw new Exception("Process function failed");
					$errcode = $r["errcode"];
					$errmsg = $r["errmsg"];
					$rtval = $r["rtval"];
					break;
                    
                 case "get_poster_list":
					$className = $action;
					$fun_obj = call_user_func(array($className, "create"));
					@$r = $fun_obj->entry($jObj['param']);
					if(empty($r))
						throw new Exception("Process function failed");
					$errcode = $r["errcode"];
					$errmsg = $r["errmsg"];
					$rtval = $r["rtval"];
					break;
                    
                  case "get_poster_contents":
					$className = $action;
					$fun_obj = call_user_func(array($className, "create"));
					@$r = $fun_obj->entry($jObj['param']);
					if(empty($r))
						throw new Exception("Process function failed");
					$errcode = $r["errcode"];
					$errmsg = $r["errmsg"];
					$rtval = $r["rtval"];
					break;

				case "get_button_csv":
					$className = $action;
					$fun_obj = call_user_func(array($className, "create"));
					@$r = $fun_obj->entry($jObj['param']);
					if(empty($r))
						throw new Exception("Process function failed");
					$errcode = $r["errcode"];
					$errmsg = $r["errmsg"];
					$rtval = $r["rtval"];
					break;

					//back_poster_contents
				case "back_poster_contents":
					$className = $action;
					$fun_obj = call_user_func(array($className, "create"));
					@$r = $fun_obj->entry($jObj['param']);
					if(empty($r))
						throw new Exception("Process function failed");
					$errcode = $r["errcode"];
					$errmsg = $r["errmsg"];
					$rtval = $r["rtval"];
					break;

                case "get_department":
                    $className = $action;
                    $fun_obj = call_user_func(array($className, "create"));
                    @$r = $fun_obj->entry($jObj['param']);
                    if(empty($r))
                        throw new Exception("Process function failed");
                    $errcode = $r["errcode"];
                    $errmsg = $r["errmsg"];
                    $rtval = $r["rtval"];
                    break;
                    
                  case "set_poster_contents":
					$className = $action;
					$fun_obj = call_user_func(array($className, "create"));
					@$r = $fun_obj->entry($jObj['param']);
					if(empty($r))
						throw new Exception("Process function failed");
					$errcode = $r["errcode"];
					$errmsg = $r["errmsg"];
					$rtval = $r["rtval"];
					break;

				case "set_user_account":
					$className = $action;
					$fun_obj = call_user_func(array($className, "create"));
					@$r = $fun_obj->entry($jObj['param']);
					if(empty($r))
						throw new Exception("Process function failed");
					$errcode = $r["errcode"];
					$errmsg = $r["errmsg"];
					$rtval = $r["rtval"];
					break;

				case "get_user_data":
					$className = $action;
					$fun_obj = call_user_func(array($className, "create"));
					@$r = $fun_obj->entry($jObj['param']);
					if(empty($r))
						throw new Exception("Process function failed");
					$errcode = $r["errcode"];
					$errmsg = $r["errmsg"];
					$rtval = $r["rtval"];
					break;


				default:
					$errcode = 4001;
					$errmsg = "No interface function ".$action;
					$rtval = NULL;
					echo "No Action";

			}
		
		}catch(Exception $e){
			echo $e->getMessage();
			$errcode = 4001;
			$errmsg = $e->getMessage();
			$rtval = NULL;
		}

		$obj = new stdClass();
		$obj->action = "result_" . $action;
		$obj->errcode = $errcode;
		$obj->errmsg     = $errmsg;
		$obj->rtval   = $rtval;
		
		if($errcode == 0){
			if(!empty($tirggerval)){
				Trigger\Client::publish($action, json_decode(json_encode($tirggerval), true));
			}
		}
		
		return json_encode($obj);
	}
	
	// 如果不是在根目录启动，则运行runAll方法
	if(!defined('GLOBAL_START')){
		Worker::runAll();
	}
	

?>

